package cn.codeforfun.interceptor.resolver;

import cn.codeforfun.util.HttpKit;
import com.qq.weixin.aes.AesException;
import com.qq.weixin.aes.WXBizMsgCrypt;
import me.chanjar.weixin.common.util.crypto.SHA1;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static cn.codeforfun.consts.WxConsts.*;

public class WxCallbackInterceptor implements HandlerInterceptor {

  private static Logger log = Logger.getLogger(WxCallbackInterceptor.class);


  @Value("${wx.token}")
  private String token;
  @Value("${wx.appid}")
  private String appid;
  @Value("${wx.secret}")
  private String appsecret;
  @Value("${wx.aeskey}")
  private String aeskey;


  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if (isConfigServerRequest(request)) {
      // 如果是服务器配置请求，则配置服务器并返回(get请求)
      if (checkSignature(request)) {
        //验证签名正确
        configServer(request, response);
      } else {
        //验证签名失败
        response.getWriter().write("你谁啊!!!");
      }
      return false;
    } else {
      // 如果不是服务器配置请求(post)
      String param = HttpKit.readData(request);
      if (param.contains(ENCRYPT)) {
        //密文需解密
        param = decryptMsg(request);
      }
      request.setAttribute(WX_REQUEST_MSG, param);
      return true;
    }
  }


  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

  }


  /**
   * 是否为开发者中心保存服务器配置的请求(get方法)
   */
  private boolean isConfigServerRequest(HttpServletRequest request) {
    return StringUtils.isNotEmpty(request.getParameter(ECHOSTR));
  }

  /**
   * 验证是不是微信发来的消息
   */
  private boolean checkSignature(HttpServletRequest request) {
    String signature = request.getParameter(SIGNATURE);//公众号
    String nonce = request.getParameter(NONCE);
    String timestamp = request.getParameter(TIMESTAMP);
    boolean flag;
    if (!SHA1.gen(token, timestamp, nonce).equals(signature)) {
      // 消息签名不正确，说明不是公众平台发过来的消息
      log.error("非法请求");
      flag = false;
    } else {
      flag = true;
    }
    return flag;
  }

  /**
   * 配置开发者中心微信服务器所需的 url 与 token
   *
   * @return true 为config server 请求，false 正式消息交互请求
   */

  public void configServer(HttpServletRequest request, HttpServletResponse response) {
    // 通过 echostr 判断请求是否为配置微信服务器回调所需的 url 与 token
    try {
      String echostr = (String) request.getAttribute(RETURN_ECHOSTR);
      if (echostr != null) {
        response.getWriter().write(echostr);
      } else {
        response.getWriter().write(request.getParameter(ECHOSTR));
      }
    } catch (IOException e) {
      log.error(e.getMessage());
    }
  }

  /**
   * 将密文解密
   *
   * @return
   */
  private String decryptMsg(HttpServletRequest request) {
    try {
      WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(token, aeskey, appid);
      return wxBizMsgCrypt.decryptMsg(
              request.getParameter(MSG_SIGNATURE),
              request.getParameter(TIMESTAMP),
              request.getParameter(NONCE),
              String.valueOf(request.getAttribute(WX_REQUEST_MSG)));
    } catch (AesException e) {
      log.error(e.getMessage());
    }
    return null;
  }
}
